/*
 * Class
 * ChooseRDialog
 */
package pl.abstractvoid.gui.configuration;

import pl.abstractvoid.settings.SettingsProvider;
import java.io.File;
import java.io.FileFilter;
import java.io.IOException;
import java.util.ArrayList;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.swing.JFileChooser;
import pl.abstractvoid.gui.UtilsGUI;
import pl.abstractvoid.languages.LanguageProvider;

/**
 * Represents the dialog window which lets user choose the R executable file.
 * 
 * @author Wojciech Szałapski
 */
public class ChooseRDialog extends javax.swing.JDialog {

    /**
     * User's R executable file.
     */
    private static File RExecutableFile;

    /**
     * Search for the R executable in most popular installation directories on 
     * Windows and Linux.
     * 
     * @return Most probable R executable file or null if the function has 
     *         found nothing suitable.
     */
    private File findR() {
        if (System.getProperty("os.name").startsWith("Windows")) {
            ArrayList<File> baseDirectories = new ArrayList<>();
            baseDirectories.add(new File("C:\\Program Files\\R"));
            baseDirectories.add(new File("C:\\Program Files (x86)\\R"));
            for (File directory : baseDirectories) {
                if (directory.isDirectory()) {
                    File[] files = directory.listFiles(new RVersionFilter());
                    for (File RDirectory : files) {
                        File binDirectory = new File(RDirectory.getAbsolutePath()
                                + File.separator + "bin");
                        if (binDirectory.isDirectory()) {
                            File RExecutable = new File(binDirectory.getAbsolutePath()
                                    + File.separator + "R.exe");
                            if (!RExecutable.isDirectory() && RExecutable.canExecute()) {
                                return RExecutable;
                            } else {
                                String[] RSubdirectories = {"x64", "i386"};
                                for (String subdirectory : RSubdirectories) {
                                    File binSubdirectoryR = new File(binDirectory.getAbsolutePath()
                                            + File.separator + subdirectory + File.separator + "R.exe");
                                    if (!binSubdirectoryR.isDirectory() && binDirectory.canExecute()) {
                                        return binSubdirectoryR;
                                    }
                                }
                            }
                        }
                    }
                }
            }
        } else {
            ArrayList<String> paths = new ArrayList<>();
            paths.add("/bin/");
            paths.add("/usr/bin/");
            paths.add("/lib64/R/bin/");
            paths.add("/usr/lib64/R/bin/");
            paths.add("/usr/share/");
            for (String path : paths) {
                File RExecutable = new File(path + "R");
                if (!RExecutable.isDirectory() && RExecutable.canExecute()) {
                    return RExecutable;
                }
            }
        }
        return null;
    }

    /**
     * Creates new dialog window.
     *
     * @param parent Parent component.
     * @param modal Modality of the dialog window.
     */
    public ChooseRDialog(java.awt.Frame parent, boolean modal) {
        super(parent, modal);
        initComponents();
        setResizable(false);
        setDefaultCloseOperation(DO_NOTHING_ON_CLOSE);
        setTitle(LanguageProvider.getInstance().getString("chooseRExecutable"));
        cancelButton.setText(LanguageProvider.getInstance().getString("cancel"));
        continueButton.setText(LanguageProvider.getInstance().getString("nextButton"));
        chooseFileButton.setText(LanguageProvider.getInstance().getString("changeButton"));
        try {
            RLogoLabel.setIcon(UtilsGUI.createImageIcon("/RLogo.png"));
        } catch (IOException ex) {
            Logger.getLogger(ChooseRDialog.class.getName()).log(Level.SEVERE, null, ex);
        }
        RExecutableFile = findR();
        if (RExecutableFile != null) {
            RExecutableTextField.setText(RExecutableFile.getAbsolutePath());
        }
    }

    /**
     * This method is called from within the constructor to initialize the form.
     * WARNING: Do NOT modify this code. The content of this method is always
     * regenerated by the Form Editor.
     */
    @SuppressWarnings("unchecked")
    // <editor-fold defaultstate="collapsed" desc="Generated Code">//GEN-BEGIN:initComponents
    private void initComponents() {

        RLogoLabel = new javax.swing.JLabel();
        RExecutableTextField = new javax.swing.JTextField();
        cancelButton = new javax.swing.JButton();
        chooseFileButton = new javax.swing.JButton();
        continueButton = new javax.swing.JButton();

        setDefaultCloseOperation(javax.swing.WindowConstants.DISPOSE_ON_CLOSE);
        getContentPane().setLayout(new org.netbeans.lib.awtextra.AbsoluteLayout());
        getContentPane().add(RLogoLabel, new org.netbeans.lib.awtextra.AbsoluteConstraints(10, 10, 64, 64));
        getContentPane().add(RExecutableTextField, new org.netbeans.lib.awtextra.AbsoluteConstraints(90, 20, 323, -1));

        cancelButton.setMaximumSize(new java.awt.Dimension(73, 23));
        cancelButton.setMinimumSize(new java.awt.Dimension(73, 23));
        cancelButton.setPreferredSize(new java.awt.Dimension(73, 23));
        cancelButton.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                cancelButtonActionPerformed(evt);
            }
        });
        getContentPane().add(cancelButton, new org.netbeans.lib.awtextra.AbsoluteConstraints(320, 50, 94, -1));

        chooseFileButton.setMaximumSize(new java.awt.Dimension(73, 23));
        chooseFileButton.setMinimumSize(new java.awt.Dimension(73, 23));
        chooseFileButton.setPreferredSize(new java.awt.Dimension(73, 23));
        chooseFileButton.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                chooseFileButtonActionPerformed(evt);
            }
        });
        getContentPane().add(chooseFileButton, new org.netbeans.lib.awtextra.AbsoluteConstraints(210, 50, 86, -1));

        continueButton.setMaximumSize(new java.awt.Dimension(73, 23));
        continueButton.setMinimumSize(new java.awt.Dimension(73, 23));
        continueButton.setPreferredSize(new java.awt.Dimension(73, 23));
        continueButton.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                continueButtonActionPerformed(evt);
            }
        });
        getContentPane().add(continueButton, new org.netbeans.lib.awtextra.AbsoluteConstraints(90, 50, 91, -1));

        pack();
    }// </editor-fold>//GEN-END:initComponents

    /**
     * Action performed on cancel button.
     * 
     * @param evt Event object passed with the action performed, not used.
     */
    private void cancelButtonActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_cancelButtonActionPerformed
        System.exit(0);
    }//GEN-LAST:event_cancelButtonActionPerformed

    /**
     * Action performed on continue button.
     * 
     * @param evt Event object passed with the action performed, not used.
     */
    private void continueButtonActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_continueButtonActionPerformed
        RExecutableFile = new File(RExecutableTextField.getText());
        try {
            SettingsProvider.getInstance().setProperty("RExecutableFile", RExecutableFile.getAbsolutePath());
        } catch (IOException ex) {
            Logger.getLogger(ChooseRDialog.class.getName()).log(Level.SEVERE, null, ex);
        }
        dispose();
    }//GEN-LAST:event_continueButtonActionPerformed

    /**
     * Action performed on choose file button.
     * 
     * @param evt Event object passed with the action performed, not used.
     */
    private void chooseFileButtonActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_chooseFileButtonActionPerformed
        JFileChooser fileChooser = new JFileChooser();
        if (fileChooser.showOpenDialog(this) == JFileChooser.APPROVE_OPTION) {
            RExecutableTextField.setText(fileChooser.getSelectedFile().getAbsolutePath());
        }
    }//GEN-LAST:event_chooseFileButtonActionPerformed

    /**
     * Returns the R executable file confirmed by the user.
     * 
     * @return R executable file.
     */
    public static File getRExecutableFile() {
        return RExecutableFile;
    }

    // Variables declaration - do not modify//GEN-BEGIN:variables
    private javax.swing.JTextField RExecutableTextField;
    private javax.swing.JLabel RLogoLabel;
    private javax.swing.JButton cancelButton;
    private javax.swing.JButton chooseFileButton;
    private javax.swing.JButton continueButton;
    // End of variables declaration//GEN-END:variables

    /**
     * File filter which accepts R installation folders with the version 
     * suffix.
     */
    private static class RVersionFilter implements FileFilter {

        /**
         * Default constructor.
         */
        public RVersionFilter() {
        }

        @Override
        public boolean accept(File dir) {
            if (!dir.isDirectory()) {
                return false;
            }
            return dir.getName().startsWith("R-");
        }
    }
}
